﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace NCM_MSTest
{
    internal static class Extensions
    {
        public static bool EqualsEx(this double l, double r, double delta = 1e-4)
        {
            return Math.Abs(l - r) < delta;
        }

        public static bool EqualsEx(this float l, float r, float delta = 1e-4f)
        {
            return Math.Abs(l - r) < delta;
        }

        public static string ToStringEx(this double[] x)
        {
            var builder = new StringBuilder();
            if (x == null || x.Length == 0)
                builder.Append("null");
            else
            {
                for (int i = 0; i < x.Length; i++)
                {
                    builder.Append(x[i].ToString("F4"));
                    if (i != x.Length - 1)
                        builder.Append(", ");
                }
            }
            return builder.ToString();
        }

        public static double[] CloneEx(this double[] x)
        {
            if (x == null)
                return null;
            var ret = new double[x.Length];
            Array.Copy(x, ret, x.Length);
            return ret;
        }

        public static double[,] CloneEx(this double[,] x)
        {
            if (x == null)
                return null;
            var ret = new double[x.GetLength(0), x.GetLength(1)];
            for (int i = 0; i < x.GetLength(0); i++)
            {
                for (int j = 0; j < x.GetLength(1); j++)
                {
                    ret[i, j] = x[i, j];
                }
            }
            return ret;
        }

        public static void Print(this double[,] x, int flen = 4)
        {
            var f = string.Format("F{0}", flen);
            var max = 0;
            for (int i = 0; i < x.GetLength(0); i++)
            {
                for (int j = 0; j < x.GetLength(1); j++)
                {
                    var s = (x[i, j]).ToString(f);
                    if (s.Length > max)
                        max = s.Length;
                }
            }
            var builder = new StringBuilder();
            for (int i = 0; i < x.GetLength(0); i++)
            {
                for (int j = 0; j < x.GetLength(1); j++)
                {
                    builder.Append(x[i, j].ToString(f).PadLeft(max));
                    builder.Append('\t');
                }
                builder.Append('\n');
            }
            Console.WriteLine(builder.ToString());
        }

        public static void PrintF(this double[,] x, int flen = 4)
        {
            Console.WriteLine($"{x.GetLength(0)}x{x.GetLength(1)}");
            x.Print(flen);
        }

        public static void PrintInv(this double[,] x, int flen = 4)
        {
            var f = string.Format("F{0}", flen);
            var max = 0;
            for (int i = 0; i < x.GetLength(1); i++)
            {
                for (int j = 0; j < x.GetLength(0); j++)
                {
                    var s = (x[j, i]).ToString(f);
                    if (s.Length > max)
                        max = s.Length;
                }
            }
            var builder = new StringBuilder();
            for (int i = 0; i < x.GetLength(1); i++)
            {
                for (int j = 0; j < x.GetLength(0); j++)
                {
                    builder.Append(x[j, i].ToString(f).PadLeft(max));
                    builder.Append('\t');
                }
                builder.Append('\n');
            }
            Console.WriteLine(builder.ToString());
        }

        public static double[] Times(this double[] A, double[] B, int Ndim, int Pdim, int Mdim)
        {
            var C = new double[Ndim * Mdim];
            //计算矩阵乘法
            for (int i = 0; i < Ndim; i++)
            {
                for (int j = 0; j < Mdim; j++)
                {
                    double sum = 0;
                    for (int k = 0; k < Pdim; k++)
                    {
                        sum += A[i * Pdim + k] * B[k * Pdim + j];
                    }
                    C[i * Mdim + j] = sum;
                }
            }
            return C;
        }

        public static double[,] Times(this double[,] A, double[,] B)
        {
            int Ndim = A.GetLength(0);
            int Pdim = A.GetLength(1);
            int _Ndim = B.GetLength(0);
            int Mdim = B.GetLength(1);
            if (Pdim != _Ndim)
                throw new Exception($"A矩阵列与B矩阵行不等:{Pdim}!={_Ndim}");
            var C = new double[Ndim, Mdim];
            //计算矩阵乘法
            for (int i = 0; i < Ndim; i++)
            {
                for (int j = 0; j < Mdim; j++)
                {
                    double sum = 0;
                    for (int k = 0; k < Pdim; k++)
                    {
                        sum += A[i, k] * B[k, j];
                    }
                    C[i, j] = sum;
                }
            }
            return C;
        }
    }
}
